#ifndef __CC_DNS_H__
#define __CC_DNS_H__

#include <stdint.h>

struct dnshdr
{
    uint16_t id;
    uint16_t flags;
    uint16_t query_count;
    uint16_t rr_count;
    uint16_t auth_count;
    uint16_t add_count;
} __attribute__((__packed__));

#define DNSHDR_LEN 12

#define DNS_FLAG_QR 0x8000
#define DNS_FLAG_AA 0x0400
#define DNS_FLAG_TC 0x0200
#define DNS_FLAG_RD 0x0100
#define DNS_FLAG_RA 0x0080
#define DNS_RCODE_MASK  0x000F
#define DNS_OPCODE_MASK 0x7800

/* DNS Opcode (type of query) */
static char* DNS_Opcode[] =
{
    "Standard Query",         /* 0: QUERY  */
    "Inverse Query",          /* 1: IQUERY */
    "Server Status Request",  /* 2: STATUS */
};

/* DNS Response Codes (error descriptions) */
static char* DNS_RCode[] =
{
    "No Error",        /* 0: ok */
    "Format Error",    /* 1: bad query */
    "Server Failure",  /* 2: server is hosed */
    "Name Error",      /* 3: name doesn't exist (authoritative) */
    "Not Implemented", /* 4: server doesn't support query */
    "Refused"          /* 5: server refused request */
};

/* DNS Generic Resource Record format (from RFC 1034 and 1035) */
struct dns_rr_hdr
{
    uint16_t rr_type;                /* RR type code (e.g. A, MX, NS, etc.) */
    uint16_t rr_class;               /* RR class code (IN for Internet) */
    uint32_t  rr_ttl;         /* Time-to-live for resource */
    uint16_t rr_rdlength;    /* length of RDATA field (in octets) */
    uint16_t rr_rdata;               /* (fieldname used as a ptr) */
};

#define DNS_RR_HDR_LEN 12

/* DNS Resource Record RDATA Field Descriptions */
static char* DNS_RR_Type [] =
{
    "<invalid>",
    "A",     // 1:  Host Address
    "NS",    // 2:  Authoritative Name Server
    "MD",    // 3:  <obsolete>
    "MF",    // 4:  <obsolete>
    "CNAME", // 5:  The true, canonical name for an alias
    "SOA",   // 6:  Start-of-Zone of authority record
    "MB",    // 7:  Mailbox   <experimental>
    "MG",    // 8:  Mailgroup <experimental>
    "MR",    // 9:  Mail Rename Domain Name <experimental>
    "NULL",  // 10: NULL Resource Record    <experimental>
    "WKS",   // 11: Well-known service description
    "PTR",   // 12: Domain Name Pointer
    "HINFO", // 13: Host Information
    "MINFO", // 14: Mailbox or Mail List information
    "MX",    // 15: Mail Exchange (from RFC 974)
    "TXT"    // 16: Text String
};

#define DNS_RRTYPE_A     1
#define DNS_RRTYPE_NS    2
#define DNS_RRTYPE_CNAME 5
#define DNS_RRTYPE_SOA   6
#define DNS_RRTYPE_WKS   11
#define DNS_RRTYPE_PTR   12
#define DNS_RRTYPE_HINFO 13
#define DNS_RRTYPE_MX    15
#define DNS_RRTYPE_TXT   16

/* DNS Resource Record Classes: */
static char* DNS_RR_Class [] =
{
    "<invalid>",
    "IN",    // 1: Internet - used for most queries!
    "CS",    // 2: CSNET <obsolete>
    "CH",    // 3: CHAOS Net
    "HS"     // 4: Hesiod
};

#define DNS_RRCLASS_IN  1
#define DNS_RRCLASS_CS  2
#define DNS_RRCLASS_CH  3
#define DNS_RRCLASS_HS  4

/* DNS SOA Resource Data Field */
struct dns_rdata_soa
{
    uint32_t soa_serial;  /* data version for this zone */
    uint32_t soa_refresh; /* time-to-live for data (in seconds) */
    uint32_t soa_retry;   /* time between retrieds (in seconds) */
    uint32_t soa_expire;  /* time until zone not auth (in seconds) */
    uint32_t soa_minimum; /* default TTL for RRs (in seconds) */
};


#define DNS_SOA_LEN 20

struct dns_rdata_wks
{
    uint32_t wks_addr;      /* IPv4 address */
    uint8_t wks_protocol;  /* Protocol (e.g. 6=TCP, 17=UDP) */
    uint8_t wks_bitmap;    /* e.g. bit 26 = SMTP (port 25) */
};


#define DNS_WKX_LEN 6

/* DNS MX Resource Data Field
 */
struct dns_rdata_mx
{
    uint16_t mx_pref;     /* Preference value */
    uint16_t mx_xchange;  /* QNAME (field used as ptr) */
};



#define DNS_MX_LEN 4

/* For Parsing Names in a Reply */
#define INDIR_MASK 0xc0

/* Number of bytes of fixed size data in query structure */
#define QFIXEDSZ 4
/* number of bytes of fixed size data in resource record */
#define RRFIXEDSZ 10

#endif

